#include "QIrcService.h"

#include <QStringList>

QIrcService::QIrcService(QObject *parent) :
    QObject(parent)
{
    QObject::connect(&m_IrcClient,SIGNAL(readyRead()), this, SLOT(dataAvailable()));
    QObject::connect(&m_IrcClient, SIGNAL(connected()), this, SLOT(connected()));
    QObject::connect(&m_IrcClient, SIGNAL(disconnected()), this, SLOT(disconnected()));
}


void QIrcService::dataAvailable()
{
    m_data += m_IrcClient.readAll(); //TODO: should read a chuck of data instead of reading everything, potentailly unsafe.
    processIncomingData();
}

void QIrcService::processIncomingData()
{
    bool lastLineNotComplete = false;
    if(m_data.at(m_data.length()-1) != '\n') {
        qDebug() << "Last line not complete";
        lastLineNotComplete = true;
    }

    QStringList list = m_data.split("\n");
    int items = list.length();
    if(lastLineNotComplete)
        items--;

    for(int i=0; i < items ; i++) {
        processMessage(list[i]);
    }

    if(lastLineNotComplete) {
        m_data = list[items];
    }
    else {
        m_data = "";
    }
}

void QIrcService::processMessage(QString srvMessage)
{
    srvMessage = srvMessage.trimmed();
    if(srvMessage.isEmpty())
        return; //Lets not waste time with empty message

    if(srvMessage.length() > 500)
        return; //Message should not be greater than 500 characters

    //TODO: This state machine needs to be done well
    int state = 0; //0 - prefix, 1 - command, 2 - middle, 3 - trailing

    QStringList srvMsgList = srvMessage.split(" ");

    QString msgSource;
    QString msgCommand;
    QString msgMiddle;
    QString msgTrailing;

    bool done = false;

    for(int index = 0; index < srvMsgList.length(); index++) {
        QString strItem = srvMsgList.at(index);
        strItem = strItem.trimmed();
        if(strItem.isEmpty())
            continue;

        switch(state) {
        case 0: {
                if(strItem[0] == ':') {
                    msgSource = strItem.mid(1); //skip the ':'
                    state = 1;
                    break;
                }
                else {
                    state = 1;
                }
            }
            //fallthrough
        case 1: {
                msgCommand = strItem;
                state = 2;
                break;
            }
        case 2: {
                if(strItem[0] != ':') {
                    msgMiddle += strItem + " ";
                    break;
                }
                else {
                    msgMiddle = msgMiddle.trimmed();
                    state = 3;
                }
                //Fallthrough for state 3
            }
        case 3: {
                for(int i = index; i < srvMsgList.length(); i++) {
                    msgTrailing += srvMsgList.at(i) + " ";
                }
                msgTrailing = msgTrailing.trimmed().mid(1);
                done = true;
                break;
            }
        }
        if(done)
            break;
    }


    if(!msgCommand.compare("PING",Qt::CaseInsensitive)) {
        sendRawCommand("PONG " + msgTrailing);
    }
    if(!msgCommand.compare("PRIVMSG",Qt::CaseInsensitive)) {
        emit onPrivMsg(msgSource,msgMiddle,msgTrailing);
    }
    if(!msgCommand.compare("JOIN",Qt::CaseInsensitive)) {
        emit onJoinEvent(msgSource,msgTrailing);
    }
    else {
        emit response(srvMessage);
    }
}

void QIrcService::connected()
{
    m_IrcClient.write("PASS manager\n"); //TODO: Send some real values here.

    QString nickStr;
    nickStr = "NICK " + mNickName + "\n";
    m_IrcClient.write(nickStr.toAscii());

    QString userStr;

    userStr = "USER ";
    userStr += "Username "; //TODO: Get this from the user
    userStr += "Host ";   //TODO: What hostdo we show?
    userStr += "Server "; //TODO: What should be the server?
    userStr += ":" + mFullName + "\n";
    m_IrcClient.write(userStr.toAscii());
    qDebug() << userStr;
    qDebug() << "Connected";
}


void QIrcService::disconnected()
{
    qDebug() << "Connectiondroped";
}

void QIrcService::connectToServer(QString server)
{
    connectToServer(server,"CuteIRC","_CuteIRC","Qt IRC",6667);
    //m_IrcClient.connectToHost(server,6667);
}

//TODO: the port should be a list of port instead.
void QIrcService::connectToServer(QString server, QString nick, QString altNickName, QString fullName, quint16 port)
{
    mNickName = nick;
    mAltNickName = altNickName;
    mFullName = fullName;
    mPort = port;
    mServerHost = server;

    m_IrcClient.connectToHost(mServerHost,mPort);
}


void QIrcService::sendCommand(QString cmd, QString param)
{

}

void QIrcService::sendRawCommand(QString cmd)
{
    //TODO: check for connection status first.
    qDebug() << cmd;
    emit response("<b>" + cmd + "</b>");
    m_IrcClient.write(cmd.toLatin1() + "\n");
}

void QIrcService::disconnect(QString msg)
{
    QString cmd;
    cmd = "QUIT :";
    if(!msg.isEmpty()) {
        cmd += msg;
    }
    cmd += "\n";
    m_IrcClient.write(cmd.toLatin1());
}
